import { DynamicIcon } from '@/components/DynamicIcon';
import { LazyImport } from '@/components/LzayImport';
import type { MenuItem } from '@/store/menuStore';
import { lazy, type ComponentType, type LazyExoticComponent } from 'react';
import { Outlet, type RouteObject } from 'react-router';

export type LazyComponent = LazyExoticComponent<ComponentType>;
export const Layout: LazyComponent = lazy(() => import('@/layout'));

type RouteMeta = {
  hidden?: boolean; // 是否隐藏此路由
  alwaysShow?: boolean; // 当你一个路由下面的 children 声明的路由大于1个时，自动会变成嵌套的模式，只有一个时，会将那个子路由当做根路由显示在侧边栏，若你想不管路由下面的 children 声明的个数都显示你的根路由，你可以设置 alwaysShow: true，这样它就会忽略之前定义的规则，
  title?: string; // 菜单栏及 tagsView 栏标题
  icon?: string; // 菜单 图标
  sort?: number; // 路由组在菜单中的顺序号
  affix?: boolean; //如果设置为true，则会一直固定在tag项中(默认 false)
  activeMenu?: string; //显示高亮的路由路径
  noTagsView?: boolean; //如果设置为true，则不会出现在tag中(默认 false)
  permission?: string[]; // 当前路由权限标识（多个请用逗号隔开），最后转成数组格式，用于与当前用户权限进行对比，控制路由显示、隐藏
};

export type RouteConfig = Omit<
  RouteObject,
  'element' | 'children' | 'Component' | 'lazy'
> & {
  element?: LazyComponent;
  children?: RouteConfig[];
  meta?: RouteMeta;
};

export const buildRoutes = (routes: RouteConfig[]): RouteObject[] => {
  return routes.map(item => {
    const { element, children, ...restProps } = item;

    // 要返回的路由对象
    let routeObject: RouteObject = {
      ...restProps,
    };

    // 递归构建子路由
    if (children) {
      routeObject.children = buildRoutes(children);
    }

    // 异步加载组件
    routeObject.element = element ? <LazyImport lazy={element} /> : undefined;

    // 如果没有 element 则传入 <Outlet />
    routeObject.element = routeObject.element ?? <Outlet />;

    // 返回路由对象
    return routeObject;
  });
};

export const initRoutes = (
  routes: RouteConfig[],
): {
  indexPath: string[];
  menus: MenuItem[];
} => {
  const indexPath: string[] = [];
  const recursion = (routes: RouteConfig[], parentPath = ''): MenuItem[] => {
    return [...routes]
      .sort((a, b) => {
        const asort = (a.meta as RouteMeta)?.sort || 0;
        const bsort = (b.meta as RouteMeta)?.sort || 0;
        return asort - bsort;
      })
      .map(route => {
        if (route.children && route.children?.length > 1) {
          route.children = recursion(route.children, route.path);
        }
        const meta = route.meta ?? {};

        const title = meta.title ?? 'no-title';

        const target: MenuItem = {
          key: route.path ? route.path : 'index_' + parentPath,
          icon: meta.icon ? <DynamicIcon icon={meta.icon} /> : '',
          label: title,
        };

        if (target.key.includes('index_')) {
          indexPath.push(target.key);
        }

        if (route.children && route.children.length > 1)
          target.children = route.children as MenuItem[];
        return target;
      });
  };

  return {
    menus: recursion(routes),
    indexPath,
  };
};
